Products Shop Support Company |

Case Study: Shell+ Documents

Fully functional P2P shared documents namespace

Shell+ Documents is a fully functional namespace extension demo that allows users to create and share virtual directories. The project is built in Delphi using Shell+ Components and the RemObjects SDK.

The Shell+ Documents project can be used as a prototype for building real namespace extensions for corporate and personal use. This article describes the process of building a true namespace extension client and application server for handling local and remote requests. You can download binaries and source code from the Shell+ Documents page.

Shell+ Documents overview

Shell+ Documents consists of two modules: the Shell namespace client and the Application Server.

The namespace client is built with Shell+ and handles the following tasks:

  • Displaying virtual folders and documents
  • Creating new virtual folders inside local and remote databases
  • Accepting files from drag&drop and copy&paste operations
  • Accepting files from Windows Applications through Save As dialogs
  • Renaming and Deleting files and folders
  • Displaying and managing additional properties for files and folders
  • Connecting and Disconnecting remote databases
  • Searching for items inside virtual folders through server call

The Application Server is built with the RemObjects SDK and handles the following tasks:

  • Handling requests to the database
  • Forwarding calls to remote servers
  • Managing connected remote servers

The data is stored in a database file handled by the Application Server. It is a simple implementation of the 'file system-in-a-file' approach.

Application Server class model

We use two generic terms in this project:

Worker - which is the class that contains implementations of all the methods

Service - which is the RO-based class accessible remotely from local or networked clients and that translates calls to the Worker-classes

The basic implementation of the Worker class is TCustomDocumentsWorker,while the basic implementation the Service class is TCustomDocumentsService.

The Worker class is inherited from the usual TDataModule, while the Service class is a RemObjects service. Both Worker and Service implement one interface: ICustomDocumentsService, which makes the class model easy to use for local and networked operations.

TCustomDocumentsService has two successors for local and remote connections. The Shell namespace extension client connects to the TLocalDocumentsService. This class automatically chooses which Worker to use (Local or Remote) and executes the method on the appropriate Worker, which is easily done, as they implement the same interface.

TLocalDocumentsWorker works directly with the database, and TRemoteDocumentsWorker executes methods of TRemoteDocumentsService on the remote server.

The best way to see the interoperability of these modules is by looking at the UML schema below (built with Model Maker). In this schema you can see how the server processes the call to the local area: LocalDocumentsService just translates the call to LocalDocumentsWorker.

And on the schema below, you can see how the server processes the call to the networked area: LocalDocumentsService translates the call to the RemoteDocumentsWorker, which in turn translates it to another server's RemoteDocumentsService and then to its LocalDocumentsWorker.

The basic element of information exchange is described by the TsdElement class. Instances of this class are used to describe databases, files and folders inside the virtual namespace.

The TsdElement class contains the ServerName property, which is used by LocalDocumentsServices to decide which worker to use.

Namespace extension implementation

The namespace extension has a much simpler design. As usual with Shell+, it has the following classes:

  • TsxModule - contains the Shell+ components that interact with the Windows Shell
  • TsxPermanentModule - contains the components that provide information that needs to be displayed in the Windows Shell
  • ServerConnection module - contains the RO components for interacting with LocalDocumentsService.
  • Several forms for different property pages
  • One form for Search Documents band

The main component on the TsxModule is TsxVirtualFolder. It contains information about NSE registration (JunctionPoint, etc,) and basic behavior like URLHandler (which allows you to display readable path names for virtual folders).

The VirtualFolder component is linked to other UI-specific components on TsxModule: TsxExtractIcon (displays a custom icon for namespace), TsxShellPropSheetExt (provides special properties dialog for NSE's root), TsxNamespaceDetails (which contains information about Details View settings), TsxSysShellView (handles general UI tasks for NSE), TSxExplorerMenu and TSxExplorerToolbar components (add commands to Explorer menu and toolbar) and TSxExplorerBand (provides ability to display custom Explorer band for searching documents server side).

Also, the VirtualFolder component is linked to the TsxByHandProvider component, which is hosted on the PermanentModule. This component allows to provide any tree-like data to the Windows Shell.

The DataProvider component is also linked to some UI-components, but these components are related to the items that DataProvider produces to the Windows Shell: TSxGrainMenu (provides menu items to the NSE elements), TSxIconList (stores icon images to be displayed for virtual items) and TsxNamespacePropertySheet (describes property pages that will be displayed for virtual items).

Shell+ uses its own class - TsxCustomDataGrain and its successors - to describe items in the virtual namespace, so several methods are available to convert information from the TsxElement class to the DataGrain class, and vice-versa. These methods are called DataGrainToSDElement and SDElementToDataGrain. As you can see from the source code, these methods are used everywhere.

The object model for this and any other namespace extensions built with Shell+ looks like this:

The TsxByHandProvider component has many different events, but its implementations are small and simple. Everything starts from OnPopulate event. It is executed when the Windows Shell needs to display the content of the root folder. The event handler retrieves and provides the list of available databases. Subsequently, when the user chooses a database or a folder within it, the event handler retrieves the list of items again and provides them to the Windows Shell as well.

One important feature in this example is the 'server based document searching'. Unlike the standard Windows Search, this feature executes the search process server side and returns only items that meet conditions entered by the user.

The search feature is implemented as a standard Explorer Band and it works as follows:

  1. When the user clicks on the "Search" button, the program creates an instance of TsdElement and stores the search query in the TsdElement.Keywords property.
  2. The program stores the created TsdElement instance in the DataGrain using the SDElementToDataGrain function and tells the Windows Shell to browse this DataGrain.
  3. The Windows Shell creates a new window and calls the DataProvider.OnPopulate event.
  4. The OnPopulate event executes a method SearchElements on the server. This method returns any found elements and OnPopulate returns them to the Windows Shell.

Download binaries and source code from the Shell+ Documents page.

© Shell+ — reprinted with kind permission.